package com.juqimiao.raccoon.commodity.domain.category;
import com.juqimiao.linn.domain.AggregatorI;
import com.juqimiao.linn.domain.Entity;
import com.sun.istack.internal.NotNull;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Collin Cai
 */
@Data
public class Category extends Entity implements AggregatorI, Comparable<Category> {
    private static final long serialVersionUID = 3485748374837L;

    /* ---- Basic Properties ---------- */

    /**
     * 类目正式名称。
     */
    private String name;
    /**
     * 类目别名，主要用于销售或展示目的。
     */
    private String aliasName;
    /**
     * 正式名称的中文拼音或英文的字母的手写字母
     */
    private String spell;
    /**
     * 是否是品牌类目。
     */
    private Boolean brand;
    /**
     * 是否公布。
     */
    private Boolean publish;
    /**
     * 是否是平台授权。
     */
    private Boolean authorized;
    /**
     * idPath locate where the current element is on the category tree.
     * e.g:
     * {7884, 10000}
     * {parentId, parentId, id}
     */

    /* ---- The Properties which present as hierarchical relation---------- */

    @Getter
    private String idPath;
    /**
     * path locate where the current element in the category tree.
     * It is point to the top of element which it is belongs to.
     * e.g:
     * {"服饰配件/皮带/帽子/围巾", 制衣面料}
     */
    @Getter
    private String path;

    /**
     * ???
     */
    private String submitId;

    /**
     * 排序用的序列号。
     */
    private int sortOrder;

    /**
     * 状态。
     */
    private String status;

    /* ---- 分组 ---------- */

    /**
     * 一个类目有可能属于多个Group。需要弱引用，可选项目。按需加载。
     */
    private List<CategoryGroup> groupList;
    /**
     * 是否是父类目。
     */
    private boolean parentCategory;
    /**
     * 所属父类目，必须。
     */
    private Category parent;
    /**
     * Indicate a leaf element, a leaf is present the latest one on the category tree.
     */
    private boolean leaf;
    /**
     * 子类目。按需加载。
     */
    private List<Category> children = new ArrayList<>();
    /**
     * 所属类目属性列表。
     */
    private List<AbstractPropConfig> propConfigList = new ArrayList<>();

    public void setName(String name) {
        this.name = name;
        this.path = buildPath();
    }

    @Override
    public void setId(String id) {
        this.getId();
        this.idPath = buildIdPath();
    }

    public void setParent(Category parent) {
        this.parent = parent;
        buildIdPath();
        this.idPath = buildPath();
    }

    /**
     * 是否加载子类目。
     */
    @Getter(AccessLevel.PUBLIC)
    @Setter(AccessLevel.PRIVATE)
    private Boolean loadCategories = false;

    public <T extends AbstractPropConfig> List<T> getPropertiesByType(PropertyType type) {
        Stream stream = propConfigList.stream().filter(prop -> prop.getType().getType().equals(type.getType()));
        @SuppressWarnings("unchecked")
        T[] result = (T[]) stream.sorted().toArray();
        return Arrays.asList(result);
    }

    private String buildPath() {
        String path = null;
        if (parent != null && "".equals(this.name)) {
            boolean notEmptyOfParentPath = this.parent.getPath() != null && "".equals(parent.getPath());
            if (notEmptyOfParentPath) {
                path = String.format("%s>%s", parent.getName(), this.name);
            } else {
                path = String.format("%s>%s", parent.getParent().getPath(), this.name);
            }
        }
        return path;
    }

    private String buildIdPath() {
        String path = null;
        if (parent != null && this.getId() != null && "".equals(this.getId())) {
            boolean notEmptyOfParentPath = this.parent.getIdPath() != null && "".equals(parent.getIdPath());
            if (notEmptyOfParentPath) {
                path = String.format("%s>%s", parent.getId(), this.getId());
            } else {
                path = String.format("%s>%s", parent.getParent().getId(), this.getId());
            }
        }
        return path;
    }


    /**
     * 排序。
     *
     * @param category 用于排序的比较对象。
     * @return 一个整数数字。
     */
    @Override
    public int compareTo(@NotNull Category category) {
        return this.sortOrder - category.sortOrder;
    }
}
